import logging

DEFAULT_SIZE = 20

_LOGGER = logging.getLogger(__name__)


def paginate(query, query_dct):
    page = int(query_dct.get('page', 1))
    size = int(query_dct.get('size', 15))
    offset = (page - 1) * size
    return query[offset:offset+size+1]


def parse_query_filter(query_dct, table):
    operators = ['__in', '__notin', '__like', '__notlike', '__lt', '__lte', '__gt', '__gte', '__neq', '__eq',
                 '__count', '__startswith', '__lower', '__contains', '__exact', '__isnull', '__iexact',
                 '__icontains', '__istartswith', '__endswith', '__iendswith', '__range', '__iregex',
                 '__max', '__min', '__stddev', '__sum', '__variance']
    fields = [field.name for field in table._meta.get_fields()]
    new_dct = {}
    key_lists = list(query_dct.keys())
    for item in key_lists:
        key = item
        for operator in operators:
            if item.endswith(operator):
                key = item.replace(operator, '')
        if key in fields:
            new_dct[item] = query_dct.get(item)
    return new_dct


def get_object(query_dct, table):
    filter_dct = parse_query_filter(query_dct, table)
    obj = table.objects.filter(**filter_dct).first()
    return obj


def list_object(query_dct, table, exclude_dct=None, disable_paginate=False, get_field=None):
    query_filter = parse_query_filter(query_dct, table)
    if get_field:
        return table.objects.filter(**query_filter).values_list(get_field, flat=True)
    if exclude_dct:
        exclude_filter = parse_query_filter(exclude_dct, table)
        query = table.objects.filter(**query_filter).exclude(**exclude_filter).values()
    else:
        query = table.objects.filter(**query_filter).values()
    total_count = query.count()
    order_by = query_dct.get('$order_by') if query_dct.get('$order_by') is not None else '-id'
    query = query.order_by(order_by)
    if not disable_paginate:
        query = paginate(query, query_dct)
    return query, total_count


def get(table, table_id):
    return table.objects.filter(id=table_id).first()


def delete(table, table_id):
    t = table.objects.select_for_update().filter(id=table_id).first()
    if t:
        t.delete()
